/*
*    Reversi Contender homepage:  http://code.google.com/p/reversi-contender
*
*    copyright 2011 steven sims <steven.joseph.sims at gmail.com>
*
*    This file is part of Reversi Contender.
*
*    Reversi Contender is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    Reversi Contender is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with Reversi Contender.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.threadswarm.reversi.rater;

import java.awt.Point;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import org.threadswarm.reversi.ReversiGame;
import org.threadswarm.reversi.Status;

/**
 *
 * @author Steven Sims <steven.joseph.sims at gmail.com>
 */
public class NegamaxInsertionSeeker implements Callable<InsertionQueryResult> {

    private final ReversiGame game;
    private final Point insertionPoint;
    private final Status insertionStatus;
    private final Status negStatus;
    private final int depth;

    public NegamaxInsertionSeeker(ReversiGame game, Point insertionPoint, Status insertionStatus, int depth) {
        this.game = game;
        this.insertionPoint = insertionPoint;
        this.insertionStatus = insertionStatus;

        if(insertionStatus == Status.WHITE)
            negStatus = Status.BLACK;
        else
            negStatus = Status.WHITE;
        this.depth = depth;
    }

    @Override
    public InsertionQueryResult call() {
        game.insert(insertionPoint);
        int value = negamax(depth, negStatus, insertionStatus);
        return new InsertionQueryResult(insertionPoint, value);
    }

    private int negamax(int depth, Status playerStatus, Status opponentStatus) {
        if(Thread.currentThread().isInterrupted())
            throw new RuntimeException("negamax task aborted");
        List<Point> availableInsertions = game.getAvailableInsertions();
        if(depth == 0 || availableInsertions.isEmpty()){
            return evaluateBoardState(playerStatus);
        }

        int best = Integer.MIN_VALUE + 1;
        for(Point insertion : availableInsertions){
            game.insert(insertion);
            int score = negamax(depth -1, opponentStatus, playerStatus);
            if(-score > best)
                best = score;
            if(best == Integer.MAX_VALUE)
                break;
            game.undo();
        }
        return best;
    }

    private int evaluateBoardState(Status status) {
        Status oppositeStatus = (status == Status.BLACK)? Status.WHITE : Status.BLACK;
        int state = 0;
        Map<Status, Integer> countMap = game.getCountMap();
        if(countMap.get(status) == 0)
            state = Integer.MIN_VALUE - 1;
        else if(countMap.get(oppositeStatus) == 0)
            state = Integer.MAX_VALUE;
        else if(countMap.get(Status.EMPTY) == 0)
            state = (countMap.get(status) >= countMap.get(oppositeStatus))? Integer.MAX_VALUE : Integer.MIN_VALUE - 1;
        else
            state = countMap.get(status);

        return state;
    }

    /**

    private getStableNodeCount(Status status) {
        int stableNodes = 0;
        Cell[][] boardCells = game.getBoardCopy();
        for(int x = 0; x < boardCells.length; x++){
            for(int y = 0; y < boardCells[0].length; y++){
                boolean stable = true;
                for(Point offset : offsetList){
                    try{
                        if(boardCells[offset.x][offset.y].getStatus() != Status.EMPTY)
                    }
                }
            }
        }
    }
     */

}
